﻿using MongoDB.Bson.Serialization.Attributes;
using MongoDB.Driver;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

namespace nMongo
{
    public partial class MongoRepository<T>
    {
        #region Single Delete (3 overloads)
        /// <summary>
        /// Delete an object from the current collection.
        /// </summary>
        /// <param name="oneObject">Object to be deleted.</param>
        /// <returns>bool: if the object was been deleted with success; false: if the object was not been deleted with success.</returns>
        public virtual bool Delete(T oneObject)
        {
            WriteConcernResult result;
            return Delete(oneObject, out result);
        }

        /// <summary>
        /// Delete an object from the current collection.
        /// </summary>
        /// <param name="oneObject">Object to be deleted.</param>
        /// <param name="result">WriteConcernResult object to receive the operation result.</param>
        /// <returns>bool: if the object was been deleted with success; false: if the object was not been deleted with success.</returns>
        public virtual bool Delete(T oneObject, out WriteConcernResult result)
        {
            return Delete(oneObject, WriteConcern.Acknowledged, out result);
        }

        /// <summary>
        /// Delete an object from the current collection.
        /// </summary>
        /// <param name="oneObject">Object to be deleted.</param>
        /// <param name="concern">Type of WriteConcern to be acknownledged.</param>
        /// <param name="result">WriteConcernResult object to receive the operation result.</param>
        /// <returns>bool: if the object was been deleted with success; false: if the object was not been deleted with success.</returns>
        public virtual bool Delete(T oneObject, WriteConcern concern, out WriteConcernResult result)
        {
            return DeleteById(OriginalCollection.GetObjectIdentity(oneObject), concern, out result);
        } 
        #endregion

        #region Multiple Delete (3 overloads)
        /// <summary>
        /// Delete a list of objects from the current collection.
        /// </summary>
        /// <param name="objects">List of objects to be deleted.</param>
        /// <returns>long: the number of the successful delete operations.</returns>
        public virtual long Delete(IEnumerable<T> objects)
        {
            IDictionary<T, WriteConcernResult> results;
            return Delete(objects, out results);
        }

        /// <summary>
        /// Delete a list of objects from the current collection.
        /// </summary>
        /// <param name="objects">List of objects to be deleted.</param>
        /// <param name="results">(IDictionary(T, WriteConcernResult)): the delete results dictionary, where the key is the object for a delete operation and the value is the WriteConcernResult object with the operation results.</param>
        /// <returns>long: the number of the successful delete operations.</returns>
        public virtual long Delete(IEnumerable<T> objects, out IDictionary<T, WriteConcernResult> results)
        {
            return Delete(objects, WriteConcern.Acknowledged, out results);
        }

        /// <summary>
        /// Delete a list of objects from the current collection.
        /// </summary>
        /// <param name="objects">List of objects to be deleted.</param>
        /// <param name="concern">Type of WriteConcern to be acknownledged.</param>
        /// <param name="results">(IDictionary(T, WriteConcernResult)): the delete results dictionary, where the key is the object for a delete operation and the value is the WriteConcernResult object with the operation results.</param>
        /// <returns>long: the number of the successful delete operations.</returns>
        public virtual long Delete(IEnumerable<T> objects, WriteConcern concern, out IDictionary<T, WriteConcernResult> results)
        {
            results = new Dictionary<T, WriteConcernResult>();
            using (this.Connection.RequestStart())
            {
                foreach (T singleObject in objects)
                {
                    WriteConcernResult result;
                    this.Delete(singleObject, concern, out result);
                    results.Add(singleObject, result);
                }
            }
            return results.Count(x => x.Value != null && x.Value.Ok);
        }
        #endregion
    }
}
